

import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutterapp/data.pb.dart';
import 'package:image_picker/image_picker.dart';
import 'package:udp/udp.dart';

//接收内容保存到文件中
class Receive{

  UDP udpClient;
  Endpoint remote;
  /// 接收的ID
  late int id;
  /// 保存的文件
  late File output; //保存位置
  late int index; //下一个要接收的packIndex
  late Timer timer; //定时器不断的通知客户端当前接收到的数据包是哪个
  int lastPackIndex=-2; //最后一次收到的packIndex
  late int? lastPackTime; //NULL=未开始接收
  var checkType=-1;
  var try_num=0;
  var try_max=3;
  Exception? lastErr;

  Receive(this.udpClient,this.remote,this.id,this.output){
    index=0;
    lastErr=null;
    timer=Timer.periodic(const Duration(seconds: 2), _check);
    lastPackTime=null;
  }

  //经过N秒收不到发送端的的pack请求则继续发送回执到发送端
  _check(Timer t) async{
    var stample = DateTime.now().millisecondsSinceEpoch;
    if(lastPackTime !=null && stample>lastPackTime!){
      log('timer tick');
      if(lastPackIndex==index-1){

        report(lastPackIndex,checkType);
        // var buffer = FileChunkCheckPack(id: id,type: checkType,packIndex: lastPackIndex).writeToBuffer(); //通知已收到
        // var packBuff = MsgPack(type: 4,chunk: buffer).writeToBuffer();
        // var v = await udpClient.send(packBuff, remote);
        log('timer send index=$lastPackIndex');
      }
    }

  }

  close(){
    timer.cancel();
  }

  //通知发送端已接收某个pack  发送回执到发送端
  Future<bool> report (int packIndex,int curCheckType)async {

    var buffer = FileChunkCheckPack(id: id,type: curCheckType,packIndex: packIndex).writeToBuffer(); //通知已收到
    var packBuff = MsgPack(type: 4,chunk: buffer).writeToBuffer();

    var v = await udpClient.send(packBuff, remote);
    if(v==packBuff.length){
      try_num=0;
      return true;
    }else{
      print('重试发送report try_index=${try_num}');
      if(try_num<try_max){
        try_num++;
        return await report(packIndex,checkType);
      }else{
        return false;
      }
    }
  }

  /// 收取内容并发送回执 checkType = 回执的type
  Future<bool> receive(FileChunkPack pack,int curCheckType) async{
    lastErr=null;
    log('receive ${pack.packIndex}/${pack.packLen} type=$curCheckType index=$index');
    if(pack.packIndex==index){
      try {
        output.writeAsBytesSync(pack.chunk, mode: FileMode.append, flush: true);
      }
      on PathAccessException catch(_err){
        lastErr=_err;
        log('写文件失败 ${_err.osError!.message}');
        return false;
      }
      checkType=curCheckType;
      lastPackTime=DateTime.now().millisecondsSinceEpoch + 5000; //+5秒
      lastPackIndex=index;
      index=pack.packIndex+1;
      if(pack.packIndex==pack.packLen-1){
        log('接收完毕');
        close();
        return true;
      }
      return await report(lastPackIndex,curCheckType);
    }
    return false;
  }

}